Str_Detect

The miracle of text detection with the wonders of THE Tidyverse!

Hello! This RMarkdown is meant to explain what the tidyverse function “str_detect” is all about and the ways you can incorporate it into your data analysis and journalistic inquiries!

So first up, we are going to load in a data set – this one happens to be from the The Armed Conflict Location & Event Data Project (ACLED), which since as early as 2014, has been tracking protests and armed conflict globally – and making the data available for public use. The data is global from the time span of January 2020 to April 2022, and was downloaded using the ACLED’s data download function. It was then read into this markdown as a csv file and renamed acled_data.

Below is the code chunk for loading in the csv file from the ACLED website!

acled_data <-
  read_csv( "acled_protests.csv")
## Rows: 582032 Columns: 31
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (18): event_id_cnty, event_date, event_type, sub_event_type, actor1, ass...
## dbl (13): data_id, iso, event_id_no_cnty, year, time_precision, inter1, inte...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
acled_data %>%
  glimpse
## Rows: 582,032
## Columns: 31
## $ data_id          <dbl> 8909166, 8909185, 8909186, 8909192, 8909221, 8909222,…
## $ iso              <dbl> 364, 275, 275, 275, 275, 275, 275, 275, 792, 792, 422…
## $ event_id_cnty    <chr> "IRN18074", "PSE14302", "PSE14303", "PSE14317", "PSE1…
## $ event_id_no_cnty <dbl> 18074, 14302, 14303, 14317, 14358, 14360, 14363, 1436…
## $ event_date       <chr> "18 March 2022", "18 March 2022", "18 March 2022", "1…
## $ year             <dbl> 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022,…
## $ time_precision   <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ event_type       <chr> "Protests", "Protests", "Riots", "Riots", "Violence a…
## $ sub_event_type   <chr> "Peaceful protest", "Peaceful protest", "Violent demo…
## $ actor1           <chr> "Protesters (Iran)", "Protesters (Palestine)", "Riote…
## $ assoc_actor_1    <chr> "Labour Group (Iran)", "Muslim Group (Palestine); Pro…
## $ inter1           <dbl> 6, 6, 5, 5, 8, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 1, 6, 6,…
## $ actor2           <chr> NA, NA, "Military Forces of Israel (2021-)", "Rioters…
## $ assoc_actor_2    <chr> NA, NA, NA, "Civilians (Palestine)", "Farmers (Palest…
## $ inter2           <dbl> 0, 0, 8, 5, 7, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,…
## $ interaction      <dbl> 60, 60, 58, 55, 78, 58, 58, 58, 60, 60, 60, 60, 60, 6…
## $ region           <chr> "Middle East", "Middle East", "Middle East", "Middle …
## $ country          <chr> "Iran", "Palestine", "Palestine", "Palestine", "Pales…
## $ admin1           <chr> "Alborz", "West Bank", "West Bank", "West Bank", "Gaz…
## $ admin2           <chr> "Karaj", "Al Quds", "Nablus", "Al Quds", "Gaza City",…
## $ admin3           <chr> "Central", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ location         <chr> "Karaj", "Al Quds - Old City", "Bayta", "Al Quds - Ol…
## $ latitude         <dbl> 35.8327, 31.7767, 32.1414, 31.7767, 31.5134, 31.8031,…
## $ longitude        <dbl> 50.9916, 35.2342, 35.2855, 35.2342, 34.4751, 35.2870,…
## $ geo_precision    <dbl> 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1,…
## $ source           <chr> "Eteraze Bazar; Iran Kargar", "Dunia Al Watan; Palest…
## $ source_scale     <chr> "New media", "National", "National", "National", "Nat…
## $ notes            <chr> "On 18 March 2022, drivers who lost vehicles in the S…
## $ fatalities       <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
## $ timestamp        <dbl> 1647870024, 1647870024, 1647870024, 1647870024, 16478…
## $ iso3             <chr> "IRN", "PSE", "PSE", "PSE", "PSE", "PSE", "PSE", "PSE…

Upon first “glimpse” of our csv file, there are 582,032 rows in the data set!

So for this example of what the str_detect function does, we will be looking at immigration related events from 2020 till 2022, tracked by the ACLED.

Str_detect – what is it?

The str_detect function of the tidyverse is a way for you to basically find keywords within your data set. This works by creating a command line to find a specific set of letters, or a phrase within text bound variables in your database. For this example we are using the ACLED database which contains a variable called “notes”.

The “notes” section contains a written narrative of the kinds of conflicts the organization has tracked. For this data frame – focused on immigration related events from 2020 till 2022 – we are going to create a str_detect command to find out the ACLED events that mention anything related to immigration or “border” in the notes column.

This data frame also includes a filter narrowing down the events shown to the United States, as well as only displaying the columns listed in the “select” function of the code chunk.

The code chunk below should, in theory, turn up any mention of “immigration” or “border” within the notes column of the ACLED data set. This is written in the code as “immigra” “|” (divider line) and “border” to show that you want the code to query both the beginning of “immigration” and “border” together – but NOT a run on phrase.

acled_data %>%
  filter( country %in% c("United States") ,
          str_detect( notes, "immigra|border"))  %>%
  select( data_id , notes, event_date , country , region ,
          event_type , actor1:assoc_actor_2, location , source ,  admin2, admin3)

Okay! Here’s our first example of how a str_detect works! So we went from 582,032 rows to only about 719 rows when we narrowed our search of the data frame down to only events that mention immigration or border within the “notes” column of the data!

But…What else??

So, finding 719 immigration related events tracked by the ACLED wasn’t enough? Okay…what about something more topical?

On February 24th, 2022 Vladimir Putin ordered Russian military forces into Ukraine – in an act that is widely being called an unprovoked invasion on a sovereign country. Like in decades before, Russia’s dicey diplomatic agenda has spurred mass outrage – and there has subsequently been events tracked by the ACLED that are spurred on by this invasion.

Below we are going to be implementing our str_detect function in order to find out how many events that the group tracks, have been about the Russian Ukrainian war.

So you set up the code chunk in the same way, except for you replace “immigra|border” to “Ukraine” – still in the notes section – to find a rough estimate of the number of events related to Ukraine.

acled_data %>%
  filter( country %in% c("United States") ,
          str_detect( notes, "Ukraine")) %>%
  count( inter1 , sort=TRUE, name="uniq_inter1") 

PS* we added a “count” function in order to simply count all the events that have “Ukraine” in the notes narrative. This should give us the same

Where to go from here

So you’ve learned the basics of str_detect! Where do you go from here?

Well, the str_detect function has a wide range of uses, not just on text features. You can find a wide range of information from querying from the function.

In the ACLED data – there are numerous variables that can have a wealth of information for data analytic or story ideas. One of the ways str_detect

For instance – what if we wanted to find only events from a certain organizing group? Well first we would need to have the name of the organization you are searching for. Let’s use “Veterans on Patrol” in order to find some of these. Here’s a trick – using a “^” before the word in your query will only show groups that start with “Vet”. Check it out below:

acled_data %>%
  filter( country %in% c("United States") ,
          str_detect( actor1 , "^Vet"))

So you can see from the table above that we ran into a problem…and a common problem for str_detect is that there are a ton of different words in this column that start with “Vet” – so lets narrow it down. If you search the data set, you’ll see that the Veterans on Patrol entries always start with “VOP:” – lets make that our query. See it below:

acled_data %>%
  filter( country %in% c("United States") ,
          str_detect( actor1 , "^VOP:"))

And when you use that code line – you see that there are 57 events out of the 719 that we started with, attributed to VOP: Veterans on Patrol. This is a simple way to query your data, especially when you’ve narrowed a potential story subject down, and want to only see those events. Likewise – this can be used to find loan data (from perhaps the PPP Loans from early in the pandemic) or even law enforcement data to aggregate where hot spot trends in police departments are.

This is just the beginning of what is capable with this function. But now, you’re ready to rock n’ roll.

I hope this has helped introduce you to the str_detect function in the “tidyverse” in R!

LS0tCnRpdGxlOiAiRXhwbGFpbmVyOiBGVU4gd2l0aCBTdHJfRGV0ZWN0ISIKYXV0aG9yOiAibmF0aGFuIGNvbGxpbnMiCmRhdGU6ICI0LzI3LzIwMjIiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdGhlbWU6IGNvc21vCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVjaG8gPSBUUlVFLAogICAgbWVzc2FnZSA9IFRSVUUsCiAgICB3YXJuaW5nID0gVFJVRSkKCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHJlYWN0YWJsZSkKCmBgYAoKIyMgU3RyX0RldGVjdAoKIyMgVGhlIG1pcmFjbGUgb2YgdGV4dCBkZXRlY3Rpb24gd2l0aCB0aGUgd29uZGVycyBvZiBUSEUgVGlkeXZlcnNlIQoKSGVsbG8hIFRoaXMgUk1hcmtkb3duIGlzIG1lYW50IHRvIGV4cGxhaW4gd2hhdCB0aGUgdGlkeXZlcnNlIGZ1bmN0aW9uICJzdHJfZGV0ZWN0IiBpcyBhbGwgYWJvdXQgYW5kIHRoZSB3YXlzIHlvdSBjYW4gaW5jb3Jwb3JhdGUgaXQgaW50byB5b3VyIGRhdGEgYW5hbHlzaXMgYW5kIGpvdXJuYWxpc3RpYyBpbnF1aXJpZXMhCgpTbyBmaXJzdCB1cCwgd2UgYXJlIGdvaW5nIHRvIGxvYWQgaW4gYSBkYXRhIHNldCAtLSB0aGlzIG9uZSBoYXBwZW5zIHRvIGJlIGZyb20gdGhlIFRoZSBBcm1lZCBDb25mbGljdCBMb2NhdGlvbiAmIEV2ZW50IERhdGEgUHJvamVjdCAoQUNMRUQpLCB3aGljaCBzaW5jZSBhcyBlYXJseSBhcyAyMDE0LCBoYXMgYmVlbiB0cmFja2luZyBwcm90ZXN0cyBhbmQgYXJtZWQgY29uZmxpY3QgZ2xvYmFsbHkgLS0gYW5kIG1ha2luZyB0aGUgZGF0YSBhdmFpbGFibGUgZm9yIHB1YmxpYyB1c2UuIFRoZSBkYXRhIGlzIGdsb2JhbCBmcm9tIHRoZSB0aW1lIHNwYW4gb2YgSmFudWFyeSAyMDIwIHRvIEFwcmlsIDIwMjIsIGFuZCB3YXMgZG93bmxvYWRlZCB1c2luZyB0aGUgQUNMRUQncyBkYXRhIGRvd25sb2FkIGZ1bmN0aW9uLiBJdCB3YXMgdGhlbiByZWFkIGludG8gdGhpcyBtYXJrZG93biBhcyBhIGNzdiBmaWxlIGFuZCByZW5hbWVkIGFjbGVkX2RhdGEuCgpCZWxvdyBpcyB0aGUgY29kZSBjaHVuayBmb3IgbG9hZGluZyBpbiB0aGUgY3N2IGZpbGUgZnJvbSB0aGUgQUNMRUQgd2Vic2l0ZSEKCmBgYHtyfQphY2xlZF9kYXRhIDwtCiAgcmVhZF9jc3YoICJhY2xlZF9wcm90ZXN0cy5jc3YiKQpgYGAKCmBgYHtyfQphY2xlZF9kYXRhICU+JQogIGdsaW1wc2UKCmBgYAoKVXBvbiBmaXJzdCAiZ2xpbXBzZSIgb2Ygb3VyIGNzdiBmaWxlLCB0aGVyZSBhcmUgNTgyLDAzMiByb3dzIGluIHRoZSBkYXRhIHNldCEKClNvIGZvciB0aGlzIGV4YW1wbGUgb2Ygd2hhdCB0aGUgc3RyX2RldGVjdCBmdW5jdGlvbiBkb2VzLCB3ZSB3aWxsIGJlIGxvb2tpbmcgYXQgaW1taWdyYXRpb24gcmVsYXRlZCBldmVudHMgZnJvbSAyMDIwIHRpbGwgMjAyMiwgdHJhY2tlZCBieSB0aGUgQUNMRUQuCgojIyBTdHJfZGV0ZWN0IC0tIHdoYXQgaXMgaXQ/CgohW10oSk9ITi5naWYpCgpUaGUgc3RyX2RldGVjdCBmdW5jdGlvbiBvZiB0aGUgdGlkeXZlcnNlIGlzIGEgd2F5IGZvciB5b3UgdG8gYmFzaWNhbGx5IGZpbmQga2V5d29yZHMgd2l0aGluIHlvdXIgZGF0YSBzZXQuIFRoaXMgd29ya3MgYnkgY3JlYXRpbmcgYSBjb21tYW5kIGxpbmUgdG8gZmluZCBhIHNwZWNpZmljIHNldCBvZiBsZXR0ZXJzLCBvciBhIHBocmFzZSB3aXRoaW4gdGV4dCBib3VuZCB2YXJpYWJsZXMgaW4geW91ciBkYXRhYmFzZS4gRm9yIHRoaXMgZXhhbXBsZSB3ZSBhcmUgdXNpbmcgdGhlIEFDTEVEIGRhdGFiYXNlIHdoaWNoIGNvbnRhaW5zIGEgdmFyaWFibGUgY2FsbGVkICJub3RlcyIuCgpUaGUgIm5vdGVzIiBzZWN0aW9uIGNvbnRhaW5zIGEgd3JpdHRlbiBuYXJyYXRpdmUgb2YgdGhlIGtpbmRzIG9mIGNvbmZsaWN0cyB0aGUgb3JnYW5pemF0aW9uIGhhcyB0cmFja2VkLiBGb3IgdGhpcyBkYXRhIGZyYW1lIC0tIGZvY3VzZWQgb24gaW1taWdyYXRpb24gcmVsYXRlZCBldmVudHMgZnJvbSAyMDIwIHRpbGwgMjAyMiAtLSB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIGEgc3RyX2RldGVjdCBjb21tYW5kIHRvIGZpbmQgb3V0IHRoZSBBQ0xFRCBldmVudHMgdGhhdCBtZW50aW9uIGFueXRoaW5nIHJlbGF0ZWQgdG8gaW1taWdyYXRpb24gb3IgImJvcmRlciIgaW4gdGhlIG5vdGVzIGNvbHVtbi4KClRoaXMgZGF0YSBmcmFtZSBhbHNvIGluY2x1ZGVzIGEgZmlsdGVyIG5hcnJvd2luZyBkb3duIHRoZSBldmVudHMgc2hvd24gdG8gdGhlIFVuaXRlZCBTdGF0ZXMsIGFzIHdlbGwgYXMgb25seSBkaXNwbGF5aW5nIHRoZSBjb2x1bW5zIGxpc3RlZCBpbiB0aGUgInNlbGVjdCIgZnVuY3Rpb24gb2YgdGhlIGNvZGUgY2h1bmsuCgpUaGUgY29kZSBjaHVuayBiZWxvdyBzaG91bGQsIGluIHRoZW9yeSwgdHVybiB1cCBhbnkgbWVudGlvbiBvZiAiaW1taWdyYXRpb24iIG9yICJib3JkZXIiIHdpdGhpbiB0aGUgbm90ZXMgY29sdW1uIG9mIHRoZSBBQ0xFRCBkYXRhIHNldC4gVGhpcyBpcyB3cml0dGVuIGluIHRoZSBjb2RlIGFzICJpbW1pZ3JhIiAiXHwiIChkaXZpZGVyIGxpbmUpIGFuZCAiYm9yZGVyIiB0byBzaG93IHRoYXQgeW91IHdhbnQgdGhlIGNvZGUgdG8gcXVlcnkgYm90aCB0aGUgYmVnaW5uaW5nIG9mICJpbW1pZ3JhdGlvbiIgYW5kICJib3JkZXIiIHRvZ2V0aGVyIC0tIGJ1dCBOT1QgYSBydW4gb24gcGhyYXNlLgoKYGBge3J9CmFjbGVkX2RhdGEgJT4lCiAgZmlsdGVyKCBjb3VudHJ5ICVpbiUgYygiVW5pdGVkIFN0YXRlcyIpICwKICAgICAgICAgIHN0cl9kZXRlY3QoIG5vdGVzLCAiaW1taWdyYXxib3JkZXIiKSkgICU+JQogIHNlbGVjdCggZGF0YV9pZCAsIG5vdGVzLCBldmVudF9kYXRlICwgY291bnRyeSAsIHJlZ2lvbiAsCiAgICAgICAgICBldmVudF90eXBlICwgYWN0b3IxOmFzc29jX2FjdG9yXzIsIGxvY2F0aW9uICwgc291cmNlICwgIGFkbWluMiwgYWRtaW4zKQpgYGAKCk9rYXkhIEhlcmUncyBvdXIgZmlyc3QgZXhhbXBsZSBvZiBob3cgYSBzdHJfZGV0ZWN0IHdvcmtzISBTbyB3ZSB3ZW50IGZyb20gNTgyLDAzMiByb3dzIHRvIG9ubHkgYWJvdXQgNzE5IHJvd3Mgd2hlbiB3ZSBuYXJyb3dlZCBvdXIgc2VhcmNoIG9mIHRoZSBkYXRhIGZyYW1lIGRvd24gdG8gb25seSBldmVudHMgdGhhdCBtZW50aW9uIGltbWlncmF0aW9uIG9yIGJvcmRlciB3aXRoaW4gdGhlICJub3RlcyIgY29sdW1uIG9mIHRoZSBkYXRhIQoKIyMgQnV0Li4uV2hhdCBlbHNlPz8KClNvLCBmaW5kaW5nIDcxOSBpbW1pZ3JhdGlvbiByZWxhdGVkIGV2ZW50cyB0cmFja2VkIGJ5IHRoZSBBQ0xFRCB3YXNuJ3QgZW5vdWdoPyBPa2F5Li4ud2hhdCBhYm91dCBzb21ldGhpbmcgbW9yZSB0b3BpY2FsP1wKXApPbiBGZWJydWFyeSAyNHRoLCAyMDIyIFZsYWRpbWlyIFB1dGluIG9yZGVyZWQgUnVzc2lhbiBtaWxpdGFyeSBmb3JjZXMgaW50byBVa3JhaW5lIC0tIGluIGFuIGFjdCB0aGF0IGlzIHdpZGVseSBiZWluZyBjYWxsZWQgYW4gdW5wcm92b2tlZCBpbnZhc2lvbiBvbiBhIHNvdmVyZWlnbiBjb3VudHJ5LiBMaWtlIGluIGRlY2FkZXMgYmVmb3JlLCBSdXNzaWEncyBkaWNleSBkaXBsb21hdGljIGFnZW5kYSBoYXMgc3B1cnJlZCBtYXNzIG91dHJhZ2UgLS0gYW5kIHRoZXJlIGhhcyBzdWJzZXF1ZW50bHkgYmVlbiBldmVudHMgdHJhY2tlZCBieSB0aGUgQUNMRUQgdGhhdCBhcmUgc3B1cnJlZCBvbiBieSB0aGlzIGludmFzaW9uLgoKQmVsb3cgd2UgYXJlIGdvaW5nIHRvIGJlIGltcGxlbWVudGluZyBvdXIgc3RyX2RldGVjdCBmdW5jdGlvbiBpbiBvcmRlciB0byBmaW5kIG91dCBob3cgbWFueSBldmVudHMgdGhhdCB0aGUgZ3JvdXAgdHJhY2tzLCBoYXZlIGJlZW4gYWJvdXQgdGhlIFJ1c3NpYW4gVWtyYWluaWFuIHdhci4KClNvIHlvdSBzZXQgdXAgdGhlIGNvZGUgY2h1bmsgaW4gdGhlIHNhbWUgd2F5LCBleGNlcHQgZm9yIHlvdSByZXBsYWNlICJpbW1pZ3JhXHxib3JkZXIiIHRvICJVa3JhaW5lIiAtLSBzdGlsbCBpbiB0aGUgbm90ZXMgc2VjdGlvbiAtLSB0byBmaW5kIGEgcm91Z2ggZXN0aW1hdGUgb2YgdGhlIG51bWJlciBvZiBldmVudHMgcmVsYXRlZCB0byBVa3JhaW5lLgoKYGBge3J9CmFjbGVkX2RhdGEgJT4lCiAgZmlsdGVyKCBjb3VudHJ5ICVpbiUgYygiVW5pdGVkIFN0YXRlcyIpICwKICAgICAgICAgIHN0cl9kZXRlY3QoIG5vdGVzLCAiVWtyYWluZSIpKSAlPiUKICBjb3VudCggaW50ZXIxICwgc29ydD1UUlVFLCBuYW1lPSJ1bmlxX2ludGVyMSIpIAoKYGBgCgpQU1wqIHdlIGFkZGVkIGEgImNvdW50IiBmdW5jdGlvbiBpbiBvcmRlciB0byBzaW1wbHkgY291bnQgYWxsIHRoZSBldmVudHMgdGhhdCBoYXZlICJVa3JhaW5lIiBpbiB0aGUgbm90ZXMgbmFycmF0aXZlLiBUaGlzIHNob3VsZCBnaXZlIHVzIHRoZSBzYW1lCgojIyBXaGVyZSB0byBnbyBmcm9tIGhlcmUKClNvIHlvdSd2ZSBsZWFybmVkIHRoZSBiYXNpY3Mgb2Ygc3RyX2RldGVjdCEgV2hlcmUgZG8geW91IGdvIGZyb20gaGVyZT8KCldlbGwsIHRoZSBzdHJfZGV0ZWN0IGZ1bmN0aW9uIGhhcyBhIHdpZGUgcmFuZ2Ugb2YgdXNlcywgbm90IGp1c3Qgb24gdGV4dCBmZWF0dXJlcy4gWW91IGNhbiBmaW5kIGEgd2lkZSByYW5nZSBvZiBpbmZvcm1hdGlvbiBmcm9tIHF1ZXJ5aW5nIGZyb20gdGhlIGZ1bmN0aW9uLgoKSW4gdGhlIEFDTEVEIGRhdGEgLS0gdGhlcmUgYXJlIG51bWVyb3VzIHZhcmlhYmxlcyB0aGF0IGNhbiBoYXZlIGEgd2VhbHRoIG9mIGluZm9ybWF0aW9uIGZvciBkYXRhIGFuYWx5dGljIG9yIHN0b3J5IGlkZWFzLiBPbmUgb2YgdGhlIHdheXMgc3RyX2RldGVjdAoKRm9yIGluc3RhbmNlIC0tIHdoYXQgaWYgd2Ugd2FudGVkIHRvIGZpbmQgb25seSBldmVudHMgZnJvbSBhIGNlcnRhaW4gb3JnYW5pemluZyBncm91cD8gV2VsbCBmaXJzdCB3ZSB3b3VsZCBuZWVkIHRvIGhhdmUgdGhlIG5hbWUgb2YgdGhlIG9yZ2FuaXphdGlvbiB5b3UgYXJlIHNlYXJjaGluZyBmb3IuIExldCdzIHVzZSAiVmV0ZXJhbnMgb24gUGF0cm9sIiBpbiBvcmRlciB0byBmaW5kIHNvbWUgb2YgdGhlc2UuIEhlcmUncyBhIHRyaWNrIC0tIHVzaW5nIGEgIlxeIiBiZWZvcmUgdGhlIHdvcmQgaW4geW91ciBxdWVyeSB3aWxsIG9ubHkgc2hvdyBncm91cHMgdGhhdCBzdGFydCB3aXRoICJWZXQiLiBDaGVjayBpdCBvdXQgYmVsb3c6CgpgYGB7cn0KYWNsZWRfZGF0YSAlPiUKICBmaWx0ZXIoIGNvdW50cnkgJWluJSBjKCJVbml0ZWQgU3RhdGVzIikgLAogICAgICAgICAgc3RyX2RldGVjdCggYWN0b3IxICwgIl5WZXQiKSkKYGBgCgpTbyB5b3UgY2FuIHNlZSBmcm9tIHRoZSB0YWJsZSBhYm92ZSB0aGF0IHdlIHJhbiBpbnRvIGEgcHJvYmxlbS4uLmFuZCBhIGNvbW1vbiBwcm9ibGVtIGZvciBzdHJfZGV0ZWN0IGlzIHRoYXQgdGhlcmUgYXJlIGEgdG9uIG9mIGRpZmZlcmVudCB3b3JkcyBpbiB0aGlzIGNvbHVtbiB0aGF0IHN0YXJ0IHdpdGggIlZldCIgLS0gc28gbGV0cyBuYXJyb3cgaXQgZG93bi4gSWYgeW91IHNlYXJjaCB0aGUgZGF0YSBzZXQsIHlvdSdsbCBzZWUgdGhhdCB0aGUgVmV0ZXJhbnMgb24gUGF0cm9sIGVudHJpZXMgYWx3YXlzIHN0YXJ0IHdpdGggIlZPUDoiIC0tIGxldHMgbWFrZSB0aGF0IG91ciBxdWVyeS4gU2VlIGl0IGJlbG93OgoKYGBge3J9CmFjbGVkX2RhdGEgJT4lCiAgZmlsdGVyKCBjb3VudHJ5ICVpbiUgYygiVW5pdGVkIFN0YXRlcyIpICwKICAgICAgICAgIHN0cl9kZXRlY3QoIGFjdG9yMSAsICJeVk9QOiIpKQpgYGAKCkFuZCB3aGVuIHlvdSB1c2UgdGhhdCBjb2RlIGxpbmUgLS0geW91IHNlZSB0aGF0IHRoZXJlIGFyZSA1NyBldmVudHMgb3V0IG9mIHRoZSA3MTkgdGhhdCB3ZSBzdGFydGVkIHdpdGgsIGF0dHJpYnV0ZWQgdG8gVk9QOiBWZXRlcmFucyBvbiBQYXRyb2wuIFRoaXMgaXMgYSBzaW1wbGUgd2F5IHRvIHF1ZXJ5IHlvdXIgZGF0YSwgZXNwZWNpYWxseSB3aGVuIHlvdSd2ZSBuYXJyb3dlZCBhIHBvdGVudGlhbCBzdG9yeSBzdWJqZWN0IGRvd24sIGFuZCB3YW50IHRvIG9ubHkgc2VlIHRob3NlIGV2ZW50cy4gTGlrZXdpc2UgLS0gdGhpcyBjYW4gYmUgdXNlZCB0byBmaW5kIGxvYW4gZGF0YSAoZnJvbSBwZXJoYXBzIHRoZSBQUFAgTG9hbnMgZnJvbSBlYXJseSBpbiB0aGUgcGFuZGVtaWMpIG9yIGV2ZW4gbGF3IGVuZm9yY2VtZW50IGRhdGEgdG8gYWdncmVnYXRlIHdoZXJlIGhvdCBzcG90IHRyZW5kcyBpbiBwb2xpY2UgZGVwYXJ0bWVudHMgYXJlLgoKVGhpcyBpcyBqdXN0IHRoZSBiZWdpbm5pbmcgb2Ygd2hhdCBpcyBjYXBhYmxlIHdpdGggdGhpcyBmdW5jdGlvbi4gQnV0IG5vdywgeW91J3JlIHJlYWR5IHRvIHJvY2sgbicgcm9sbC4KCkkgaG9wZSB0aGlzIGhhcyBoZWxwZWQgaW50cm9kdWNlIHlvdSB0byB0aGUgc3RyX2RldGVjdCBmdW5jdGlvbiBpbiB0aGUgInRpZHl2ZXJzZSIgaW4gUiEKCiFbXShtaWNrLmdpZikK